﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using Flurl.Http;
using Newtonsoft.Json.Linq;
using Pay.Core;
using Pay.DTO.hfnative;
using Pay.DTO.hfpay;

namespace Pay.Service {
	public class HfSign {
		public HfSign() {
		}

#if DEBUG
		protected string _hf_api_url = "http://17.57.33.35:6088/hftrans2/ws/httpAccess/";
		public string hf_privateKey = "30820275020100300d06092a864886f70d01010105000482025f3082025b020100028181009c94ae9a0d4fc00ae1b6deb8d4c21102c735a78d64c805af42a9f04f55efc83e31847962a9c6b4e525003c16791e48fcb31003d980971b7e342d044ad0ccc8e10a8ad36ba473e1da3dda963690671bba89ef99829706419d30fc1a0dec3c3c1046ebf125cbf43a955befacaf8023d5a777e3b6f97e44ead6606b714a77bbb54902030100010281807deccd26b381e9ae56ac5d1e446cf68547748d1597718db0cf6a200b8dcf533941558ad1a03c600ad0e1097201622bcc9ead488b49713cf9183903f4af4ba258a2f6e1c0ab467e5b8d18705badc087ce6564528a1e9e9e5bd9cceb04419c2552e446dbdf0afb1245c1a712b0b7dff08cb1941699345de20dd35e6ea5707dad09024100a8984601e1f2e2eb24ab91d838cfd10a4ef0cf191f4222c88b3cf7fa8e5c7edf6602b3a1f27b4fabfa2fabd2bb49a308943b64e802397b5875ae0285812b6b6b024100edc1eb57afae84c6e24c516471325f561ff4fd4396172738b41eb7ade86ab76a660e569dff0474f9f962b9afddebf19224bfbda5c225b0edb6254c2af517631b02405229dbbc612460c85e17ab3d27fac79271845439970d412c610736870a4833a0a5f35d1de8b185d3775b322ec20d9201c553e8ca5503348498dd53e7425b29bf02405a3b463db906da8d4045067ec01705e781a95094ddd95ba1417a86eb1151aeda4a71169e4fb23952c53a9a8e0c030763175f4d7223047ae93c3f5b70d223561102405f3af03ef90c86f83b30827fb05abba0d01e2e37de8ba5ae6bd0db3b4c4c0719e5346104701f686cb674a39a8c30630d6c96ebe33efc1e503081a39cdd6be109";
		protected string _hf_publicKey = "30819f300d06092a864886f70d010101050003818d00308189028181009c94ae9a0d4fc00ae1b6deb8d4c21102c735a78d64c805af42a9f04f55efc83e31847962a9c6b4e525003c16791e48fcb31003d980971b7e342d044ad0ccc8e10a8ad36ba473e1da3dda963690671bba89ef99829706419d30fc1a0dec3c3c1046ebf125cbf43a955befacaf8023d5a777e3b6f97e44ead6606b714a77bbb5490203010001";

#else
		protected string _hf_api_url = "http://17.57.33.2:7080/hftrans2/ws/httpAccess/";
		public string hf_privateKey = "30820275020100300d06092a864886f70d01010105000482025f3082025b02010002818100ab3dfac238fece193e410b9f78b35d6ec5eb9b164b46f6165cefdd850a4988d2529de6902c3a97b27ab06d073481453c3060fc0374a15d8045c5db4f0cb2e9ce9fd504d68b4ce00f3bdfe42c665271ebe48e378caa04317e2aa8c69649a5ae9f07ef63b7a3cc5222254c4842035ebd1077c532d17a5680c533fb2a8c160ceead020301000102818028326c629b2e7502c7f24ce02a5d3059886c3e0385b82a9c2544c92329bf093715ddaaf9bce82423e958f0bef83c401c58deeb49845f3cab97b5523dc4255b6c9a602c99dc3008b788d4f1284f8cdbbbb80ceca895d14168e0faf7fdb9df331910364bca6c7b9d13e2e3981325d93109fc546e767721af5a8af488e3f9079001024100b94eaf677f92d395487214ba852c51b51628b3c95e729f7b4688dbe6e830aeda07927d1c5e9199c53ac49729af0aae7a41cda376aea4e852d1f9ed81a3b6f481024100ec91aa99a1fe64bee2507d5a2be11cbe43cd683f53a89d28869b4ec8a4bc89aed8f7ecd9f7c87900ed55965b979e17da481931b828148866c333a1026d59f42d024035575a146fdba2fe38e165e81f0797e9899c63cc565ca65dc4fb0659dc828f0281e580101784cfffbf1ff1e774d49d4ee1fc40ce9c0d2a3714ec5d9ad0b68c8102403ba67b3ae3e2ee6a474c7e5f17435ae90ad5a75c986ea2ba0e3ee8fda4b4398f51fc29c7c837cf7311650c55aa045e05573aab13c15f74095d5d0e533b597c3d02404474405bccc12f328ba9b780e66c64235123d4ec15c0936d9ff94134a186752888fecf98b7796dab309bffbb6e27f4c2448d5e9102ecdedd82e4b2e9a0bfb804";
		protected string _hf_publicKey = "30819f300d06092a864886f70d010101050003818d0030818902818100ab3dfac238fece193e410b9f78b35d6ec5eb9b164b46f6165cefdd850a4988d2529de6902c3a97b27ab06d073481453c3060fc0374a15d8045c5db4f0cb2e9ce9fd504d68b4ce00f3bdfe42c665271ebe48e378caa04317e2aa8c69649a5ae9f07ef63b7a3cc5222254c4842035ebd1077c532d17a5680c533fb2a8c160ceead0203010001";
#endif
		//HF扫码
#if DEBUG
		public string _nativePayUrl = "https://apihf.onepaypass.com/aps/cloudplatform/api/trade.html";
		public string t0_native_key = "";
		public string t0_native_mchid = "";
		public string t1_native_key = "";
		public string t1_native_mchid = "";
		public string native_pri = "";
		public string native_pub = "";
#else
		public string _nativePayUrl = "https://apihf.onepaypass.com/aps/cloudplatform/api/trade.html";
		public string t0_native_key = "d8ee8334241e460eaea793e6e839174c";
		public string t0_native_mchid = "000100045";
		public string t1_native_key = "d40b2c30de1941258bdbde0e796f26eb";
		public string t1_native_mchid = "000100044";
		public string native_pri = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKLzyrHYoiMN1rou0Q5jV6E1fy/J2OMMSWjsPnQUIjshFlPLQe6vB4BXO5lDo7+wM7D/HRaMzYC8EDT5Q3aHNCoQWCWlcNhTLelPlrYEdK/oJ0H0Czyt1SJeaD76YdHDYptoNze7uKlyB/5j5ZAE/FRQqgXQ5EalBA8gAeqHtiNzAgMBAAECgYBeTqvrm83SbcrtO/Uf15y6nwR5+t68ILtHrxpCAfkBsZeDbWo+Iiw8OcAzZnMZmHeCI1OJXnn83Fqg3fYOXhdwpQRyWQ4z6wNxZqY8G9nHopw00nvhw6ADF95TBRZtMTVqr+d+tD5eGs/7UGIL0++29YQXQcAEfnfgxJquU2ZVSQJBAPFu6mWCKZmr8IORv4qrvl/iaDPPH9it6EHOcfpbZjAYWXzNg/i3Hwq+St1yimKhwEf2ZE+09Rw8DhGkxNP5sd0CQQCsyLCbF+9zT5rKOfs7x0ld9uXzA1B2Z+poglH34dmL8Uste2iddw9Migr+4lUi2KN0do5+FAdf8c8DLU7AcN2PAkAn3g7qsDG6ZIAU2c5tUargHnzigUNa/myp4TNFCi63pm2whCdUvLhth7rJEo7zdo5P08oAt3r6LJiOJU0zS7opAkA4HHiV9WDyvqBTGh9Hm4Fs/XhRwfrIaRjL1b6O1I6UjsjOPWyM7pROU+ocOh5R0a7LbJD7yr9WXi3PJ1CS2FRrAkEAqPSlDZXQ0cmwl1IgyRWPBR2rmrF2rseip9RAOJ6dt3UkAvT5OPYIPNqe0WA6vjYZQVHunGmvHR6BTORKGNHXsA==";
		public string native_pub = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCi88qx2KIjDda6LtEOY1ehNX8vydjjDElo7D50FCI7IRZTy0HurweAVzuZQ6O/sDOw/x0WjM2AvBA0+UN2hzQqEFglpXDYUy3pT5a2BHSv6CdB9As8rdUiXmg++mHRw2KbaDc3u7ipcgf+Y+WQBPxUUKoF0ORGpQQPIAHqh7YjcwIDAQAB";
#endif
		//代付
#if DEBUG
		public string merNo = "";
		public string ftp_ip = "123.56.16.246";
		public string ftp_name = "yunshang";
		public string ftp_pwd = "strong123,";
#else
		public string merNo = "5321001155";
		public string ftp_ip = "17.57.33.37";
		public string ftp_name = "fjsfb_bp";
		public string ftp_pwd = "fjsfb1234";
#endif

		#region 请求POST和SIGN
		/// <summary>
		/// HF银联请求通道封装
		/// </summary>
		/// <returns>The pay gateway.</returns>
		/// <param name="model">Model.</param>
		/// <typeparam name="T">The 1st type parameter.</typeparam>
		public async Task<HFBankData<head_base, T>> PayGateway<T>(object model) where T : body_base, new() {
			var log = IocHelper.Get<ILogHelper>("info");
			var xml = model.ToXml();
			var data = xml.InnerXml;
			log.Info(data);
#if DEBUG
			test_body_base body = new test_body_base {
				respCode = "0", state = "0", requestUrl = "", origRespCode = "0", origTranState = "0", transDate = DateTime.Now.ToString("yyyyMMddHHmmss")
			};
			var obj = JToken.Parse(model.ToJson());
			var dto = obj["head"].ToObject<head_base>();
			if (dto.tranCode == "2012" || dto.tranCode == "1201")
				body.respCode = "0000";
			if (dto.tranCode == "2003") {
				body.respCode = "0000";
				body.origRespCode = "0";
			}
			//if (dto.tranCode == "2002")//测试快捷支付不确定
			//body.respCode = "1";
			//if (dto.tranCode == "2002")//测试快捷支付失败
			//	body.respCode = "2";
			T t = JToken.Parse(body.ToJson()).ToObject<T>();
			return new HFBankData<head_base, T> { body = t };
#else
			try {
				var formDataBytes = data == null ? new byte[0] : Encoding.UTF8.GetBytes(data);
				var content = new ByteArrayContent(formDataBytes);
				var resp = await _hf_api_url.PostAsync(content).ReceiveString();
				var result = resp.ToObjectByXml<HFBankData<head_base, T>>();
				log.Info(result.ToJson());
				return result;
			} catch (FlurlHttpException ex) {
				log.Error(ex.Message);
				return null;
			}
#endif
		}

		/// <summary>
		/// HF银联请求通道封装sign.
		/// </summary>
		/// <returns>The sign.</returns>
		/// <param name="model">Model.</param>
		/// <typeparam name="T">The 1st type parameter.</typeparam>
		/// <typeparam name="V">The 2nd type parameter.</typeparam>
		public string Sign<T, V>(HFBankData<T, V> model) where T : new() where V : new() {
			var result = _sign(model);
			result = RSAFromPkcs.sign2Hex(result, hf_privateKey, "utf-8");
			return result;
		}

		private string _sign<T, V>(HFBankData<T, V> model) where T : new() where V : new() {
			var collection = new SortedDictionary<string, string>();
			string json = model.head.ToJson();
			var collection_head = json.ToObject<Dictionary<string, string>>();
			collection_head.Remove("signature");
			json = model.body.ToJson();
			var collection_body = json.ToObject<Dictionary<string, string>>();
			foreach (var item in collection_head) {
				collection.Add(item.Key, item.Value);
			}
			foreach (var item in collection_body) {
				collection.Add(item.Key, item.Value);
			}
			string result = string.Empty;
			foreach (var kv in collection)
				result += "&" + kv.Key + "=" + kv.Value;
			result = result.Trim('&');
			var log = IocHelper.Get<ILogHelper>("info");
			log.Info(result);
			return result;
		}

		/// <summary>
		/// 分大小写排列
		/// </summary>
		/// <returns>The sign2.</returns>
		/// <param name="model">Model.</param>
		/// <typeparam name="T">The 1st type parameter.</typeparam>
		/// <typeparam name="V">The 2nd type parameter.</typeparam>
		public string Sign2<T, V>(HFBankData<T, V> model) where T : new() where V : new() {
			var result = _sign2(model);
			result = RSAFromPkcs.sign2Hex(result, hf_privateKey, "utf-8");
			return result;
		}
		/// <summary>
		/// 分大小写排列
		/// </summary>
		/// <returns>The sign2.</returns>
		/// <param name="model">Model.</param>
		/// <typeparam name="T">The 1st type parameter.</typeparam>
		/// <typeparam name="V">The 2nd type parameter.</typeparam>
		private string _sign2<T, V>(HFBankData<T, V> model) where T : new() where V : new() {
			var collection = new Dictionary<string, string>();
			string json = model.head.ToJson();
			var collection_head = json.ToObject<Dictionary<string, string>>();
			collection_head.Remove("signature");
			json = model.body.ToJson();
			var collection_body = json.ToObject<Dictionary<string, string>>();
			foreach (var item in collection_head) {
				collection.Add(item.Key, item.Value);
			}
			foreach (var item in collection_body) {
				collection.Add(item.Key, item.Value);
			}
			var keys = collection.Select(c => c.Key).ToArray();
			Array.Sort(keys, (a, b) => string.Compare(a, b, StringComparison.Ordinal));
			string result = string.Empty;
			foreach (var key in keys)
				result += "&" + key + "=" + collection[key];
			result = result.Trim('&');
			var log = IocHelper.Get<ILogHelper>("info");
			log.Info(result);
			return result;
		}

		/// <summary>
		/// 综合验签
		/// </summary>
		public bool VerifySign<T, V>(HFBankData<T, V> model, string sign) where T : new() where V : new() {
			var sortJson = _sign(model);
			var result = RSAFromPkcs.verify2Hex(sortJson, sign, _hf_publicKey, "utf-8");
			return result;
		}
		#endregion

		#region 扫码
		public async Task<T> PostNative<T>(object model) where T : hf_pay_resp, new() {
			var log = IocHelper.Get<ILogHelper>("info");
			log.Info(model.ToJson());
			try {
				var result = await _nativePayUrl.PostJsonAsync(model).ReceiveJson<T>();
				log.Info(result.ToJson());
				return result;
			} catch (FlurlHttpException ex) {
				log.Error(ex.Message);
				return null;
			}
		}

		/// <summary>
		/// HF扫码通道封装sign.
		/// </summary>
		/// <returns>The sign.</returns>
		/// <param name="model">Model.</param>
		public string Sign(object model, string md5key) {
			var sortJson = SecuritySignHelper.JsonToKeyQuery(model.ToJson()) + "&key=" + md5key;
			var result = SecureHelper.MD5(sortJson).ToUpper();
			return result;
		}

		/// <summary>
		/// 扫码验签
		/// </summary>
		/// <returns><c>true</c>, if sign was verifyed, <c>false</c> otherwise.</returns>
		/// <param name="model">Model.</param>
		/// <param name="sign">Sign.</param>
		public bool VerifySign(JObject model, string sign, string settle_type) {
			string md5key = "";
			if (settle_type == "T0") md5key = t0_native_key;
			else md5key = t1_native_key;
			var log = IocHelper.Get<ILogHelper>("info");
			var sortJson = SecuritySignHelper.HFJsonToKeyQuery(model.ToJson()) + "&key=" + md5key;
			log.Info(sortJson);
			var result = SecureHelper.MD5(sortJson).ToUpper();
			log.Info(result);
			return result == sign;
		}

		/// <summary>
		/// 扫码提现
		/// </summary>
		/// <returns>The native2.</returns>
		/// <param name="model">Model.</param>
		/// <typeparam name="T">The 1st type parameter.</typeparam>
		public async Task<T> PostNative2<T>(object model) where T : hf_pay_resp, new() {
			var log = IocHelper.Get<ILogHelper>("info");
			log.Info(model.ToJson());
			try {
				var result = await "https://apihf.onepaypass.com/aps/cloudplatform/api/withdraw_fixed.html".PostJsonAsync(model).ReceiveJson<T>();
				log.Info(result.ToJson());
				return result;
			} catch (FlurlHttpException ex) {
				log.Error(ex.Message);
				return null;
			}
		}

		/// <summary>
		/// 扫码T0余额
		/// </summary>
		/// <returns>The native2.</returns>
		/// <param name="model">Model.</param>
		/// <typeparam name="T">The 1st type parameter.</typeparam>
		public async Task<T> PostNative3<T>(object model) where T : hf_pay_resp, new() {
			var log = IocHelper.Get<ILogHelper>("info");
			log.Info(model.ToJson());
			try {
				var result = await "https://apihf.onepaypass.com/aps/cloudplatform/api/agent_account/query.html".PostJsonAsync(model).ReceiveJson<T>();
				log.Info(result.ToJson());
				return result;
			} catch (FlurlHttpException ex) {
				log.Error(ex.Message);
				return null;
			}
		}

		/// <summary>
		/// HF扫码通道封装sign.
		/// </summary>
		/// <returns>The sign.</returns>
		/// <param name="model">Model.</param>
		public string Sign2(object model, string md5key) {
			var sortJson = SecuritySignHelper.JsonToKeyQuery(model.ToJson()) + "&key=" + md5key;
			var result = RSAFromPkcs.sign(sortJson, native_pri, "utf-8");
			return result;
		}
		#endregion
	}
}
